﻿using System;
using System.ComponentModel;
using System.Windows.Threading;

using VSTalk.Engine.Core.XmppConnection;
using VSTalk.Logger;
using VSTalk.Model;
using VSTalk.Tools;

using agsXMPP;

using log4net;

namespace VSTalk.Engine.Core.EntitySession
{
    public class ClientContext : IClientContext
    {
        private static readonly ILog _log = LoggerFactory.Create(typeof(ClientContext));

        private readonly XmppClientConnection _connection;

        private ClientState _state = ClientState.Disconnected;

        private IActionWrapper<object, XmppConnectionState> _onXmppConnectionStateChanged;
        
        private IActionWrapper<object, Exception> _onError;

        public Jid Jid
        {
            get { return _connection.MyJID; }
        }

        public Client Client { get; private set; }

        public ClientState State
        {
            get { return _state; }
            set
            {
                _state = value;
                PropertyChanged.Notify(() => State);
            }
        }

        public ClientContext(Client client)
        {
            Client = client;
            _connection = AppServices
                    .Get<IConnectionManager>()
                    .GetOrCreateConnection(Client)
                    .Connection;
        }

        public void StartListen()
        {
            var dispatcher = Dispatcher.CurrentDispatcher;
            
            _onXmppConnectionStateChanged = dispatcher.Wrap<object, XmppConnectionState>(OnXmppConnectionStateChanged);
            _connection.OnXmppConnectionStateChanged += _onXmppConnectionStateChanged.Exec;
            
            _onError = dispatcher.Wrap<object, Exception>(OnError);
            _connection.OnError += _onError.Exec;
        }

        public void StopListen()
        {
            _connection.OnXmppConnectionStateChanged -= _onXmppConnectionStateChanged.Exec;
            _connection.OnError -= _onError.Exec;
        }

        private void OnXmppConnectionStateChanged(object sender, XmppConnectionState state)
        {
            _log.InfoFormat("State changed client {0} state {1}", Client.Id, state);
            if (state == XmppConnectionState.Disconnected)
            {
                State = ClientState.Disconnected;
            }
            else if (state == XmppConnectionState.SessionStarted)
            {
                State = ClientState.Connected;
            }
            else
            {
                State = ClientState.Connecting;
            }
        }

        protected void OnError(object sender, Exception ex)
        {
            State = ClientState.Disconnected;
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}